﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Yglab.Models;
using Yglab.MyLib;

namespace Yglab.Controllers
{
    public class JournalController : Controller
    {
        private YgContext conn = new YgContext();

        // tüm publication ları listelemeye gerek yok. üstte breadcrumb olarak önceki sayıya git felan olursa yeterli.

        [HttpGet]
        public ActionResult InitializeJournal(string journalpath)
        {
            User currentUser = MySingletonSession.Current.CurrentUser;
            if(currentUser == null)
                return RedirectToAction("Index", "Home");

            Journal journal = conn.Journals.Include("Editor").FirstOrDefault(j => j.PathName.Equals(journalpath));
            Invitation i = conn.Invitations.FirstOrDefault(inv => (inv.InvitedUser.Id == currentUser.Id || inv.InvitedUserEmail.Equals(currentUser.Email)) && inv.State == 3);

            if(i == null )
                return RedirectToRoute("Journal", new { action = "Articles", controller = "Journal", journalpath = journalpath });

            Gui_InitializeJournals gui = new Gui_InitializeJournals
            {
                Journal = journal,
                Subjects = conn.Subjects.ToList(),
                Sciences = conn.Sciences.ToList()
            };
            return View(gui);
        }

        [HttpPost]
        public ActionResult InitializeJournal(Gui_InitializeJournals gui_initializeJournal, string journalpath)
        {
            User currentUser = conn.Users.Find(MySingletonSession.Current.CurrentUser.Id);
            Journal journal = conn.Journals.Include("Subjects").Include("Sciences").FirstOrDefault(j => j.PathName == journalpath);
            Invitation i = conn.Invitations.FirstOrDefault(inv => inv.InvitedUser.Id == currentUser.Id  && inv.State == 3);
            
            journal.Editor = currentUser;
            journal.ArticleNum = gui_initializeJournal.ArticleNum;
            foreach (int subjectId in gui_initializeJournal.SubjectIds)
                journal.Subjects.Add(conn.Subjects.Find(subjectId));
            foreach (int scienceId in gui_initializeJournal.ScienceIds)
                journal.Sciences.Add(conn.Sciences.Find(scienceId));
            foreach (string question in gui_initializeJournal.Questions)
            {
                if (question != null && !question.Equals(""))
                    conn.Questions.Add(new Question { Journal = journal, QuestionText = question });
            }
            
            i.State = 1;

            conn.SaveChanges();

            ViewBag.journalpath = journalpath;
            
            return RedirectToRoute("Journal", new{action = "Articles", controller = "Journal", journalpath = journalpath} );
        }
        
        // Bir sayıya ait olan makaleler listelenecek. eğer year, noInYear yoksa son sayı sistemden çekilerek bu parametreler oluşturulacak.
        public ActionResult Articles(string journalpath, Nullable<int> year, Nullable<int> noInYear)
        {
            ViewBag.journalpath = journalpath;

            return View();
        }

        // verilen year ve noInYear değerlerini karşılayan article'ı göster. bu parametreler zorunlu.
        // üye değilse sadece kısa bilgiler.
        // üye ise makaleye ait tüm bilgiler
        public ActionResult Versionn(string journalpath, int id) 
        {   // görüntüleyenin kim olduğuna göre makalenin versiyonları görüntülenir veya görüntülenmez. 
            
            User currentUser = conn.Users.Find(MySingletonSession.Current.CurrentUser.Id);

            Versionn disVersionn = conn.Versionns.Include("Subjects").Include("Sciences").Include("References").Include("Refrees").
                Include("Article").Include("Article.Author").Include("Article.Journal").Include("Article.Journal.Editor").
                Include("Article.Versionns").Include("Article.Journal.Questions").FirstOrDefault(v => v.Id == id);

            Versionn previousVersionn = disVersionn.Article.Versionns.Where(v => v.VersionnNo < disVersionn.VersionnNo).
                OrderByDescending(v => v.VersionnNo).FirstOrDefault();
            Versionn nextVersionn = disVersionn.Article.Versionns.Where(v => v.VersionnNo > disVersionn.VersionnNo).
                OrderBy(v => v.VersionnNo).FirstOrDefault();

            Gui_Versionn g = new Gui_Versionn
            {
                DisplayingVersionn = disVersionn,
                PreviousVersionn = previousVersionn,
                NextVersionn = nextVersionn,
            };

            bool is_NotYetAcceptedRefree = conn.Invitations.Include("Versionn").Include("User").
                Any(i=>i.InvitationType == 2 && i.State == 3 && i.InvitedUser.Id == currentUser.Id && i.Versionn.Id == disVersionn.Id);

            if (currentUser == null)
                g.RoleForThisArticle = 1;
            else if (currentUser.Id == disVersionn.Article.Author.Id)
                g.RoleForThisArticle = 2;
            else if (disVersionn.Refrees.Any(r => r.Id == currentUser.Id) || is_NotYetAcceptedRefree)
                g.RoleForThisArticle = 3;
            else if (disVersionn.Article.Journal.Editor.Id == currentUser.Id)
                g.RoleForThisArticle = 4;
            else
                g.RoleForThisArticle = 1;

            
            // hakemler için
            if (disVersionn.State > 1 && g.RoleForThisArticle == 3 &&
                conn.Evaluations.Include("Refree").Include("Versionn").
                Any(ev => ev.Versionn.Id == disVersionn.Id && ev.Refree.Id == currentUser.Id))
            {
                g.EvaluationOfRefree = conn.Evaluations.Include("Answers").Include("Answers.Question").Include("Versionn").FirstOrDefault(ev => ev.Versionn.Id == disVersionn.Id && ev.Refree.Id == currentUser.Id);
            }
            else { g.EvaluationOfRefree = null;  }

            // editör için
            if (disVersionn.State > 1 && g.RoleForThisArticle == 4)
            {
                g.Evaluations = conn.Evaluations.Include("Answers").Include("Versionn").Where(ev => ev.Versionn.Id == disVersionn.Id).ToList();
            }
            else { g.Evaluations = null; }

            if (disVersionn.State == 2 && g.RoleForThisArticle == 4)
                g.NotYetAcceptedInvitations = conn.Invitations.Include("Versionn").Include("InvitedUser").Where(inn => inn.State == 3 && inn.InvitationType == 2 && inn.Versionn.Id == disVersionn.Id).ToList();
            else { g.NotYetAcceptedInvitations = null; }

            // yazar için
            if (disVersionn.State == 4 && g.RoleForThisArticle == 2)
            {
                g.Evaluations = conn.Evaluations.Include("Answers").Include("Versionn").Where(ev => ev.Versionn.Id == disVersionn.Id).ToList();
            }
            else { g.Evaluations = null; }

            return View(g);
        }

        [HttpGet]
        public ActionResult NewVersionNewArticle(string journalpath)
        {
            Gui_NewArticle n = new Gui_NewArticle
            {
                Journal = conn.Journals.FirstOrDefault(j => j.PathName == journalpath),
                Sciences = conn.Sciences.ToList(),
                Subjects = conn.Subjects.ToList()
            };
            return View(n);
        }
        [HttpPost]
        public ActionResult NewVersionNewArticle(string journalpath, Gui_NewArticle arc )
        {
            Journal journal = conn.Journals.Include("Editor").FirstOrDefault(j => j.PathName == journalpath);
            User currentUser = conn.Users.Find(MySingletonSession.Current.CurrentUser.Id);
            Article newArticle = conn.Articles.Add(new Article{ Author=currentUser, Journal = journal, State = 1});
            Versionn newVersionn = conn.Versionns.Add(new Versionn{
                Abstract=arc.Abstract,
                Article=newArticle,
                State = 1,
                Title=arc.Title,
                VersionnNo=1
            });

            newVersionn.Subjects = new List<Subject>();
            foreach (int subjectId in arc.SubjectIds)
                newVersionn.Subjects.Add(conn.Subjects.Find(subjectId));

            newVersionn.Sciences = new List<Science>();
            foreach (int scienceId in arc.ScienceIds)
                newVersionn.Sciences.Add(conn.Sciences.Find(scienceId));

            newVersionn.References = new List<Reference>();
            foreach (string reference in arc.References)
                newVersionn.References.Add(new Reference { ReferencedArticleTitle = reference, Type = 2 });

            conn.Notifications.Add(new Notification { Type = 4, User = journal.Editor, Versionn = newVersionn });

            conn.SaveChanges();

            return RedirectToRoute("Journal", new { action = "Versionn", controller = "Journal", journalpath = journalpath, id = newVersionn.Id });
        }
        
        public ActionResult SendArticleToRefrees(int id, List<string> Refrees, string journalpath)
        {   // editör olarak
            // sadece ilk versiyon da hakemler eklenecek. hakem listesi her versiyonda değişmiyor.

            Journal journal = conn.Journals.FirstOrDefault(j => j.PathName == journalpath);
            Versionn versionn = conn.Versionns.Include("Article").FirstOrDefault(v => v.Id == id);

            foreach (string refreeEmail in Refrees)
            {
                if (refreeEmail != null && refreeEmail != "")
                {
                    if (conn.Users.Any(u => u.Email == refreeEmail))
                    {
                        Invitation addedInv = conn.Invitations.Add(new Invitation
                        {
                            Versionn = versionn,
                            InvitationType = 2,
                            UserType = 1,
                            InvitedUser = conn.Users.FirstOrDefault(u => u.Email == refreeEmail),
                            State = 3
                        });
                        conn.Notifications.Add(new Notification
                        {
                            Invitation = addedInv,
                            Type = 2,
                            User = conn.Users.FirstOrDefault(u => u.Email == refreeEmail)
                        });
                    }
                    else
                    {
                        conn.Invitations.Add(new Invitation
                        {
                            Versionn = versionn,
                            InvitationType = 2,
                            InvitedUserEmail = refreeEmail,
                            UserType = 2,
                            State = 3
                        });
                    }
                }
            }

            versionn.State = 2;

            conn.SaveChanges();

            return RedirectToRoute("Journal", new { action = "Versionn", controller = "Journal", journalpath = journalpath, id = versionn.Id });
        }

        public ActionResult RefuseEvaluating(int id)
        {   // hakem olarak
            // bir versiyon için değerlendirme reddedilince artık önceki versiyonlarında hakemliğinden çıkarılır. 
            return View();
        }

        public ActionResult EvaluateTheArticle(Dictionary<int, int> answrs, string journalpath, int id, string opinion)
        {

            Versionn  v = conn.Versionns.Include("Article.Journal.Editor").Include("Refrees").FirstOrDefault(ve => ve.Id == id);
            User currentUser = conn.Users.Find(MySingletonSession.Current.CurrentUser.Id);

            Evaluation e = conn.Evaluations.Add(new Evaluation
            {
                IsCompleted = true,
                Opinion = opinion,
                Versionn = v,
                Refree = currentUser,
                Answers = new List<Answer>()
            });

            foreach (var ans in answrs)
            {
                Question tq = conn.Questions.FirstOrDefault(qu => qu.Id == ans.Key);
                Answer a = new Answer { Question = tq, Result = ans.Value };
            
                e.Answers.Add(a);
            }

            v.Refrees.Add(currentUser);

            Invitation inv = conn.Invitations.Include("InvitedUser").Include("Versionn").FirstOrDefault(i => i.InvitationType == 2 && i.InvitedUser.Id == currentUser.Id && i.Versionn.Id == v.Id);
            inv.State = 1;

            conn.SaveChanges();

            if (!(conn.Invitations.Include("Versionn").Any(invi => invi.InvitationType == 2 && invi.Versionn.Id == v.Id && invi.State == 3)))
            {
                v.State = 3;
                conn.Notifications.Add(new Notification { Type = 5, Versionn = v, User = v.Article.Journal.Editor });
            }

            conn.SaveChanges();

            return RedirectToRoute("Journal", new { action = "Versionn", controller = "Journal", journalpath = journalpath, id = v.Id });
            
        }

        public ActionResult DecideArticle(string journalpath, int id, string opinion, int desiciontype)
        {   // Editör olarak
            // bu işlem hakeme gönderilmeden de yapılıyor olabilir.

            Journal journal = conn.Journals.FirstOrDefault(j => j.PathName == journalpath);
            Versionn versionn = conn.Versionns.Include("Article").Include("Article.Author").FirstOrDefault(v => v.Id == id);
            User currentUser = conn.Users.Find(MySingletonSession.Current.CurrentUser.Id);

            versionn.State = 4;
            versionn.EditorOpinion = opinion;
            Notification notif = conn.Notifications.Add(new Notification { Type=6, User=versionn.Article.Author, Versionn = versionn });
            versionn.DesicionType = desiciontype;

            if (desiciontype == 1)
            {
                versionn.Article.State = 3;
            }
            if (desiciontype == 2)
            {
                versionn.Article.State = 2;
            }

            conn.SaveChanges();

            return RedirectToRoute("Journal", new { action = "Versionn", controller = "Journal", journalpath = journalpath, id = versionn.Id });
        }


    }
}
